import pandas as pd
import plotly.express as px
from nicegui import ui, app
import asyncio
from datetime import datetime

# 设置中文字体支持
app.add_static_files('/static', '.')


# 数据加载和预处理
def load_and_preprocess_data(file_path):
    # 加载数据
    df = pd.read_csv(file_path)

    # 数据清洗
    # 处理日期列
    date_columns = ['arrival_date', 'adoption_date']
    for col in date_columns:
        df[col] = pd.to_datetime(df[col], errors='coerce')

    # 计算在收容所的天数
    df['days_in_shelter'] = (df['adoption_date'] - df['arrival_date']).dt.days
    # 处理未被收养的情况
    df.loc[df['adopted'] == False, 'days_in_shelter'] = -1

    # 处理数值列缺失值
    numeric_cols = df.select_dtypes(include='number').columns
    df[numeric_cols] = df[numeric_cols].apply(lambda x: x.fillna(x.mean() if x.name != 'adopter_age' else -1))

    # 处理分类列缺失值
    categorical_cols = df.select_dtypes(include=['object', 'bool']).columns
    for col in categorical_cols:
        if col not in ['adopter_id', 'adopter_name', 'adopter_city']:
            df[col] = df[col].fillna('Unknown')

    # 删除重复行
    df = df.drop_duplicates()

    return df


# 创建收养情况饼图
def create_adoption_pie(df):
    adoption_counts = df['adopted'].value_counts().reset_index()
    adoption_counts.columns = ['adopted', 'count']
    adoption_counts['status'] = adoption_counts['adopted'].apply(lambda x: '已收养' if x else '未收养')

    fig = px.pie(
        adoption_counts,
        values='count',
        names='status',
        color='status',
        color_discrete_map={'已收养': 'green', '未收养': 'red'},
        title='宠物收养情况分布',
        hole=0.3
    )

    fig.update_layout(
        height=500,
        font=dict(family="SimHei, WenQuanYi Micro Hei, Heiti TC"),
        legend_title_text='收养状态'
    )

    return fig


# 创建物种收养柱状图
def create_species_adoption_bar(df):
    species_adoption = df.groupby(['species', 'adopted']).size().unstack().fillna(0)
    species_adoption['total'] = species_adoption.sum(axis=1)
    species_adoption = species_adoption.sort_values('total', ascending=False).drop('total', axis=1)

    fig = px.bar(
        species_adoption,
        barmode='group',
        title='不同物种的收养情况',
        labels={'value': '数量', 'species': '物种', 'adopted': '收养状态'},
        color_discrete_map={True: 'green', False: 'red'}
    )

    fig.update_layout(
        height=600,
        font=dict(family="SimHei, WenQuanYi Micro Hei, Heiti TC"),
        xaxis_title='物种',
        yaxis_title='数量',
        margin=dict(l=40, r=40, t=50, b=100),  # 调整边距
        autosize=True,  # 启用自动大小
        barmode='group',
        bargap=0.15,  # 柱形之间的间距
        bargroupgap=0.1  # 组之间的间距
    )
    fig.update_xaxes(tickangle=45)
    fig.for_each_trace(lambda t: t.update(name='已收养' if t.name == 'True' else '未收养'))

    return fig


# 创建收养时间散点图
def create_adoption_time_scatter(df):
    # 只选择已收养的宠物
    adopted_pets = df[df['adopted'] == True].copy()

    fig = px.scatter(
        adopted_pets,
        x='arrival_date',
        y='days_in_shelter',
        color='species',
        hover_name='pet_name',
        size='age_years',
        size_max=30,
        title='宠物在收容所停留时间',
        labels={
            'arrival_date': '到达日期',
            'days_in_shelter': '停留天数',
            'species': '物种',
            'age_years': '年龄'
        }
    )

    fig.update_layout(
        height=600,
        font=dict(family="SimHei, WenQuanYi Micro Hei, Heiti TC"),
        xaxis_title='到达收容所日期',
        yaxis_title='在收容所停留天数'
    )

    return fig


# 创建收养人年龄分布直方图
def create_adopter_age_histogram(df):
    # 过滤有效年龄数据
    valid_ages = df[df['adopter_age'] > 0]['adopter_age']

    fig = px.histogram(
        valid_ages,
        nbins=10,  # 修正：使用 nbins 参数
        title='收养人年龄分布',
        labels={'value': '年龄', 'count': '人数'},
        color_discrete_sequence=['blue']
    )

    fig.update_layout(
        height=500,
        font=dict(family="SimHei, WenQuanYi Micro Hei, Heiti TC"),
        xaxis_title='年龄',
        yaxis_title='收养人数'
    )

    return fig


# 创建初始品种图表
def create_initial_breed_chart(df):
    # 生成一个空的初始图表
    fig = px.bar(title='请选择物种查看品种详情')
    fig.update_layout(
        height=500,
        font=dict(family="SimHei, WenQuanYi Micro Hei, Heiti TC")
    )
    return fig


# 创建宠物数据表格
def create_pet_table(df):
    columns = [
        {'name': 'pet_id', 'label': '宠物ID', 'field': 'pet_id', 'sortable': True},
        {'name': 'pet_name', 'label': '宠物名称', 'field': 'pet_name', 'sortable': True},
        {'name': 'species', 'label': '物种', 'field': 'species', 'sortable': True},
        {'name': 'breed', 'label': '品种', 'field': 'breed', 'sortable': True},
        {'name': 'age_years', 'label': '年龄(岁)', 'field': 'age_years', 'sortable': True},
        {'name': 'gender', 'label': '性别', 'field': 'gender', 'sortable': True},
        {'name': 'adopted', 'label': '是否被收养', 'field': 'adopted', 'sortable': True},
        {'name': 'days_in_shelter', 'label': '停留天数', 'field': 'days_in_shelter', 'sortable': True}
    ]

    return columns


# 主应用
def main():
    # 加载数据（请替换为实际文件路径）
    df = load_and_preprocess_data('pet_adoption_center.csv')

    # 创建主界面
    with ui.header().classes('bg-blue-600 text-white shadow-lg'):
        ui.label('宠物收养中心数据分析').classes('text-2xl font-bold ml-4')
        with ui.row().classes('ml-auto mr-4'):
            ui.button('刷新数据', on_click=lambda: refresh_data()).classes(
                'bg-white text-blue-600 hover:bg-blue-500 hover:text-white transition-colors')

    with ui.tabs().classes('bg-blue-500 text-white') as tabs:
        ui.tab('收养概况', icon='pie_chart')
        ui.tab('物种分析', icon='pets')
        ui.tab('时间分析', icon='timeline')
        ui.tab('收养人分析', icon='people')
        ui.tab('数据表格', icon='table_view')

    with ui.tab_panels(tabs, value='收养概况').classes('p-4'):
        with ui.tab_panel('收养概况'):
            with ui.card().classes('w-full'):
                ui.plotly(create_adoption_pie(df)).classes('w-full h-[500px]')

                # 统计信息卡片
                with ui.row().classes('mt-4'):
                    total_pets = len(df)
                    adopted_pets = df['adopted'].sum()
                    adoption_rate = (adopted_pets / total_pets * 100) if total_pets > 0 else 0

                    with ui.card().classes('w-1/4'):
                        ui.label(f'总宠物数: {total_pets}')
                    with ui.card().classes('w-1/4'):
                        ui.label(f'已收养: {adopted_pets}')
                    with ui.card().classes('w-1/4'):
                        ui.label(f'未收养: {total_pets - adopted_pets}')
                    with ui.card().classes('w-1/4'):
                        ui.label(f'收养率: {adoption_rate:.2f}%')

        with ui.tab_panel('物种分析'):
            with ui.card().classes('w-full'):
                ui.plotly(create_species_adoption_bar(df)).classes('w-full h-[600px]')

                # 物种筛选下拉框
                with ui.row().classes('mt-4'):
                    species_list = ['全部'] + sorted(df['species'].unique().tolist())
                    species_select = ui.select(
                        options=species_list,
                        value='全部',
                        label='选择物种查看详情'
                    ).classes('w-1/3')

                    def update_breed_chart():
                        selected_species = species_select.value
                        if selected_species == '全部':
                            breed_data = df
                        else:
                            breed_data = df[df['species'] == selected_species]

                        breed_adoption = breed_data.groupby(['breed', 'adopted']).size().unstack().fillna(0)
                        breed_adoption['total'] = breed_adoption.sum(axis=1)
                        breed_adoption = breed_adoption.sort_values('total', ascending=False).head(10).drop('total',
                                                                                                            axis=1)

                        fig = px.bar(
                            breed_adoption,
                            barmode='group',
                            title=f'{selected_species}品种收养情况（前10）',
                            labels={'value': '数量', 'breed': '品种', 'adopted': '收养状态'},
                            color_discrete_map={True: 'green', False: 'red'}
                        )

                        fig.update_layout(
                            height=500,
                            font=dict(family="SimHei, WenQuanYi Micro Hei, Heiti TC")
                        )

                        fig.for_each_trace(lambda t: t.update(name='已收养' if t.name == 'True' else '未收养'))

                        # 修正：正确更新 Plotly 组件
                        breed_chart.figure = fig
                        breed_chart.update()

                ui.button('查看品种详情', on_click=update_breed_chart).classes('ml-2')

                # 创建图表时保存引用
                breed_chart = ui.plotly(create_initial_breed_chart(df)).classes('w-full h-[500px] mt-4')

        with ui.tab_panel('时间分析'):
            with ui.card().classes('w-full'):
                ui.plotly(create_adoption_time_scatter(df)).classes('w-full h-[600px]')

                # 按月份统计收养数量
                df['arrival_month'] = df['arrival_date'].dt.to_period('M')
                monthly_arrivals = df.groupby('arrival_month').size().reset_index(name='count')
                monthly_arrivals['arrival_month'] = monthly_arrivals['arrival_month'].astype(str)

                fig = px.line(
                    monthly_arrivals,
                    x='arrival_month',
                    y='count',
                    title='每月宠物到达数量趋势',
                    labels={'count': '数量', 'arrival_month': '月份'},
                    markers=True
                )

                fig.update_layout(
                    height=500,
                    font=dict(family="SimHei, WenQuanYi Micro Hei, Heiti TC")
                )

                ui.plotly(fig).classes('w-full h-[500px] mt-4')

        with ui.tab_panel('收养人分析'):
            with ui.card().classes('w-full'):
                ui.plotly(create_adopter_age_histogram(df)).classes('w-full h-[500px]')

                # 之前养宠数量分析
                prev_pets_data = df[df['adopted'] == True]['adopter_previous_pets'].value_counts().sort_index()
                fig = px.bar(
                    prev_pets_data,
                    title='收养人之前养宠数量分布',
                    labels={'index': '之前养宠数量', 'value': '收养人数量'}
                )

                fig.update_layout(
                    height=500,
                    font=dict(family="SimHei, WenQuanYi Micro Hei, Heiti TC")
                )

                ui.plotly(fig).classes('w-full h-[500px] mt-4')

        with ui.tab_panel('数据表格'):
            with ui.card().classes('w-full'):
                with ui.row().classes('mb-4'):
                    search_input = ui.input(label='搜索宠物名称或ID').classes('w-1/3')
                    species_filter = ui.select(
                        options=['全部'] + sorted(df['species'].unique().tolist()),
                        value='全部',
                        label='物种筛选'
                    ).classes('w-1/4')
                    adoption_filter = ui.select(
                        options=['全部', '已收养', '未收养'],
                        value='全部',
                        label='收养状态'
                    ).classes('w-1/4')
                    ui.button('搜索', on_click=lambda: update_table()).classes('bg-blue-600 text-white')

                columns = create_pet_table(df)
                data_table = ui.table(columns=columns, rows=[], pagination=10).classes('w-full')

                # 格式化表格数据
                def format_rows(dataframe):
                    rows = []
                    for _, row in dataframe.iterrows():
                        rows.append({
                            'pet_id': row['pet_id'],
                            'pet_name': row['pet_name'],
                            'species': row['species'],
                            'breed': row['breed'],
                            'age_years': row['age_years'],
                            'gender': row['gender'],
                            'adopted': '是' if row['adopted'] else '否',
                            'days_in_shelter': row['days_in_shelter'] if row['days_in_shelter'] != -1 else '未收养'
                        })
                    return rows

                # 更新表格数据
                def update_table():
                    filtered_data = df.copy()

                    # 应用搜索过滤
                    search_text = search_input.value.lower()
                    if search_text:
                        filtered_data = filtered_data[
                            filtered_data['pet_name'].str.lower().str.contains(search_text) |
                            filtered_data['pet_id'].str.lower().str.contains(search_text)
                            ]

                    # 应用物种过滤
                    if species_filter.value != '全部':
                        filtered_data = filtered_data[filtered_data['species'] == species_filter.value]

                    # 应用收养状态过滤
                    if adoption_filter.value == '已收养':
                        filtered_data = filtered_data[filtered_data['adopted'] == True]
                    elif adoption_filter.value == '未收养':
                        filtered_data = filtered_data[filtered_data['adopted'] == False]

                    data_table.rows = format_rows(filtered_data)
                    data_table.update()

                # 初始加载表格数据
                update_table()

    # 刷新数据函数
    async def refresh_data():
        with ui.spinner(size='xl'):
            await asyncio.sleep(0.5)  # 模拟加载延迟
            global df
            df = load_and_preprocess_data('pet_adoption_center.csv')
            update_table()
            ui.notify('数据已刷新', type='positive', position='top-right')

    # 运行应用
    ui.run(title='宠物收养中心数据分析', dark=True)


if __name__ in {"__main__", "__mp_main__"}:
    main()